package chaoyue.study.basic;

import lombok.AllArgsConstructor;

/**
 * 方法参数传递
 * 其实对于值传递和引用传递本质上是一样的
 * 都是把变量名所指的那个内存地址中保存的内容传递给方法
 * 但是对于包装类和String是特殊的，打断点可以看到，是在重新赋值的时候创建了一个新的对象，参数中的对象还是原来那个对象
 * 对于一般的对象和数组，重新赋值的时候不会创建新的对象，所以方法中的修改就会影响到原来的对象
 * 就算一般的对象使用final修饰 也没有用（即包装类和String的这种特性并不是因为是被final修饰 而是他们本身就是特殊的）
 * 参数传递其实就是给参数赋值，和执行=运算符的效果是一样的
 */
public class MethodParam {
    public static void main(String[] args) {
        System.out.println("-- Integer 类型测试 --");
        Integer i = 10;
        test(i); // 重新创建一个Integer对象传入（包装类特例）
        System.out.println(i);// 10

        System.out.println("-- String 类型测试 --");
        String s = "hello";
        test(s); // 重新创建一个String对象传入（String类特例）
        System.out.println(s); // hello

        System.out.println("-- 普通 类型测试 --");
        TestClass t = new TestClass(10);
        test(t); // 将原有的t引用传入
        System.out.println(t.i); // 20

        System.out.println("-- 普通final 类型测试 --");
        TestFinalClass f = new TestFinalClass(10);
        test(f); // 将原有的t引用传入
        System.out.println(f.i); // 20
    }

    private static void test(Integer i) {
        i = 20;
    }

    private static void test(String s) {
        s = "sss";
    }

    private static void test(TestClass t) {
        System.out.println("test3:" + t);
        t.i = 20;
    }

    private static void test(TestFinalClass t) {
         t.i = 20;
    }

    @AllArgsConstructor
    private static class TestClass {
        int i;
    }

    @AllArgsConstructor
    private static final class TestFinalClass {
        int i;
    }
}
